/*
 *  Copyright (C) 2010 Glauco
 * 
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 * 
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 * 
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.balisunrise.swing.builders;

import java.util.ArrayList;
import java.util.List;
import javax.swing.JPanel;
import org.balisunrise.annotation.EventType;
import org.balisunrise.annotation.PanelType;
import org.balisunrise.annotation.util.AnnotationsUtilitiesException;
import org.balisunrise.annotation.util.FieldUtilities;
import org.balisunrise.annotation.util.NameUtil;
import org.balisunrise.annotation.util.PanelUtilities;
import org.balisunrise.application.Application;
import org.balisunrise.builder.BuilderException;
import org.balisunrise.common.Action;
import org.balisunrise.common.ActionProvider;
import org.balisunrise.common.BindingGroup;
import org.balisunrise.common.EntityPanel;
import org.balisunrise.common.FieldLayout;
import org.balisunrise.common.PanelField;
import org.balisunrise.swing.commons.listeners.EntityPanelListener;
import org.balisunrise.swing.components.panel.FieldsPanel;
import org.balisunrise.swing.components.panel.MultiPanel;
import org.balisunrise.swing.components.panel.layouts.AssociatedPanelsLayoutBuilder;
import org.balisunrise.swing.components.panel.layouts.DefaultFieldLayoutBuilder;


/**
 *
 * @author Glauco
 */
public class EntityPanelBuilder implements org.balisunrise.builder.EntityPanelBuilder{

    private static final String MESSAGE = "Erro ao construir uma EntityPanel.\n";

    @Override
    public EntityPanel create(Class entityClass, String alias)
            throws BuilderException {

        if(entityClass == null){
            throw new BuilderException(MESSAGE +
                    "entityClass não pode ser nulo.");
        }

        if(alias == null){
            throw new BuilderException(MESSAGE +
                    "alias não pode ser nulo.");
        }

        try{
            PanelUtilities pu = PanelUtilities.create(entityClass, alias);
            return create(pu);
        }catch(AnnotationsUtilitiesException aue){
            throw new BuilderException(MESSAGE +
                    aue.getMessage(), aue.getCause());
        }
    }

    @Override
    public EntityPanel create(PanelUtilities panelUtilities)
            throws BuilderException {

        if(panelUtilities == null){
            throw new BuilderException(MESSAGE +
                    "panelUtilities não pode ser nulo.");
        }

        // cria painel
        org.balisunrise.swing.commons.EntityPanel ep =
                new org.balisunrise.swing.commons.EntityPanel();

        JPanel visualRepresentation;

        // se for painel SINGLE
        if (panelUtilities.type == PanelType.SINGLE){

            // cria lista auxiliar de FieldLaouts a partir do PanelField
            List<FieldLayout> aux = new ArrayList<FieldLayout>();

            // cria os campos do painel.
            for (FieldUtilities fu : panelUtilities.fields) {
                PanelField pf = Application.get()
                        .getVisualEntityManager()
                        .getPanelFieldBuilder()
                        .buildPanelField(fu);
                // dono
                pf.setOwner(ep);
                ep.getLayouts().add(pf);
                aux.add(pf);
            }

            // cria painel
            visualRepresentation = new FieldsPanel(
                    aux,
                    new DefaultFieldLayoutBuilder());

        }else{ // se não for painel SINGLE

            List<EntityPanel<JPanel>> panels =
                    new ArrayList<EntityPanel<JPanel>>();

            // cria os paineis associados
            for (PanelUtilities apu : panelUtilities.associatedPanelsUtilities){
                // atribui o painel pai.
                EntityPanel aep = create(apu);
                aep.setOwner(ep);
                panels.add(aep);
            }
            // atribui os paineis associados
            ep.setAssociatedPanels(panels);

            // lista dos paineis
            List<JPanel> panelList = new ArrayList<JPanel>();
            for (EntityPanel<JPanel> p : panels) {
                panelList.add(p.getVisualRepresentation());
            }
            
            // cria painel de paineis
            visualRepresentation = new MultiPanel(
                    panelList,
                    new AssociatedPanelsLayoutBuilder(panelUtilities.type));
        }

        BindingGroup bindingGroup =
                Application.get().getBindingBuilder().createBindingGroup();

        // atribui os dados
        ep.setAlias(panelUtilities.alias);
        ep.setEntityClass(panelUtilities.entityClass);
        ep.setType(panelUtilities.type);
        ep.setVisualRepresentation(visualRepresentation);
        ep.setBindingGroup(bindingGroup);
        ep.setTitle(panelUtilities.title);

        // provedor de ações
        ActionProvider ap = Application.get().getActionMapManager()
                .getActionProvider(panelUtilities.entityClass);

        // cria listener de ações de bind
        EntityPanelListener epl = new EntityPanelListener();
        ep.addEntityPanelListener(epl);

        // cria ações de eventos bind
        Action[] as = ap.getActions(EventType.PANEL_AFTER_BIND,
                panelUtilities.alias, null);
        for (Action action : as) {
            action.setOwner(ep);
            epl.addAfterBindAction(action);
        }

        // cria ações de evento de unbind
        as = ap.getActions(EventType.PANEL_AFTER_UNBIND,
                panelUtilities.alias, null);
        for (Action action : as) {
            action.setOwner(ep);
            epl.addAfterUnbindAction(action);
        }

        // nome do painel
        String name = NameUtil.buildName(ep);
        ep.setName(name);

        // representação visual
        ep.getVisualRepresentation().setName(name);
        ep.getVisualRepresentation().getAccessibleContext()
                .setAccessibleName(name);
        ep.getVisualRepresentation().getAccessibleContext()
                .setAccessibleDescription(panelUtilities.title);
        
        return ep;
    }

}
